#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from random import randint, choice
from exception import *


# 资源类型
PropertyType = {
    "未知": False,
    "障碍": False,
    "起点": True,
    "路径": True,
    "终点": True,
    "迷雾": True,
    "地雷": True,         # 炸四周随机一格，开箱子领奖励，并驱散该格子周围3*3迷雾
    "炸弹": True,         # 炸以自己为中心的3*3格子，开箱子领奖励，并驱散该格子周围5*5迷雾
    "手雷": True,         # 炸以距自己1格以外的任意一点为中心的3*3格子，开箱子领奖励，并驱散中心点周围5*5迷雾
    "宝箱": True
}


class Property:

    def __init__(self, x, y, typ, walked=False):
        """
        :param x: 坐标x
        :param y: 坐标y
        :param typ: 类型, str
        """
        self.typ = typ
        self.can_be_walk = PropertyType.get(self.typ, False)       # 是否可被走过
        self.x = x
        self.y = y
        self.walked = walked
        self.current = False

    def __str__(self):
        if self.typ in ["起点", "路径", "终点"]:
            string = '\033[42m{}\033[0m'
        elif self.typ in ["障碍"]:
            string = '\033[41m{}\033[0m'
        elif self.typ in ["地雷", "炸弹", "手雷"]:
            string = '\033[44m{}\033[0m'
        elif self.typ in ["宝箱"]:
            string = '\033[46m{}\033[0m'
        else:
            string = '{}'
        return string.format(self.typ)

    @classmethod
    def make_new_property(cls, x, y):
        daze = randint(1, 100)
        if daze < 70:
            return cls(x, y, "路径")
        elif daze < 80:
            return cls(x, y, "障碍")
        elif daze < 85:
            return cls(x, y, "地雷")
        elif daze < 90:
            return cls(x, y, "炸弹")
        elif daze < 95:
            return cls(x, y, "手雷")
        else:
            return cls(x, y, "宝箱")

    @classmethod
    def explore_property(cls, x, y):
        return cls(x, y, "路径")

    def trigger(self, n):
        """
        触发该道具
        :param n: 迷宫的边长
        :return: list[tuple(), ...]
        """
        def get_range(x, y, m, n_):
            """
            获取棋盘中指定位置x, y周围一圈m*m的x_range, y_range
            :param x:
            :param y:
            :param m:
            :param n_: 棋盘边长
            :return:
            """
            if m * 2 > n_ - 1:
                raise PointCoordinateError([x, y, m, n_])
            if x >= n_ or y >= n_ or x < 0 or y < 0:
                raise PointCoordinateError([x, y, m, n_])
            else:
                if m <= x <= n_ - m - 1:
                    x_range_ = list(range(x - m, x + m + 1))
                elif x < m:
                    x_range_ = list(range(0, x + m + 1))
                else:
                    x_range_ = list(range(x - m , n_))
                if m <= y <= n_ - m - 1:
                    y_range_ = list(range(y - m, y + m + 1))
                elif y < m:
                    y_range_ = list(range(0, y + m + 1))
                else:
                    y_range_ = list(range(y - m, n_))
                return x_range_, y_range_


        # 如果是路，则返回周围1格内的所有点的坐标
        if self.typ in ["起点", "终点", "路径"]:
            x_range, y_range = get_range(self.x, self.y, 1, n)
            clear_result = [[x, y] for x in x_range for y in y_range]
            explore_result = []
            return clear_result, explore_result
        # 如果是宝箱，则返回周围1格内的所有点的坐标
        if self.typ in ["宝箱"]:
            x_range, y_range = get_range(self.x, self.y, 1, n)
            clear_result = [[x, y] for x in x_range for y in y_range]
            explore_result = [[self.x, self.y]]
            return clear_result, explore_result
        # 如果是地雷，则先选取周围1格内的任一点，返回以该点为中心的1格内所有点的坐标
        elif self.typ == "地雷":
            x_range, y_range = get_range(self.x, self.y, 1, n)
            clear_result = [[x, y] for x in x_range for y in y_range]
            bomb_pos = choice(clear_result)
            x_range, y_range = get_range(bomb_pos[0], bomb_pos[1], 1, n)
            for x in x_range:
                for y in y_range:
                    if [x, y] not in clear_result:
                        clear_result.append([x, y])
            explore_result = [[x, y] for x in x_range for y in y_range]
            return clear_result, explore_result
        # 如果是炸弹，则先选取周围1格内的所有点，返回以该点为中心的1格内所有点的坐标
        elif self.typ == "炸弹":
            x_range, y_range = get_range(self.x, self.y, 1, n)
            explore_result = [[x, y] for x in x_range for y in y_range]
            clear_result = set()
            for bp in explore_result:
                x_range, y_range = get_range(bp[0], bp[1], 1, n)
                for x in x_range:
                    for y in y_range:
                        clear_result.add((x, y))
            return list(clear_result), explore_result
        # 如果是手雷，则先选取周围1格外的任一点，返回以该点为中心的1格内所有点的坐标
        elif self.typ == "手雷":
            maze = [[x, y] for x in range(n) for y in range(n)]
            x_range, y_range = get_range(self.x, self.y, 1, n)
            clear_result = [[x, y] for x in x_range for y in y_range]
            while True:
                new_position = choice(maze)
                if new_position[0] not in x_range and new_position[1] not in y_range:
                    break
            x_range, y_range = get_range(new_position[0], new_position[1], 1, n)
            explore_result = [[x, y] for x in x_range for y in y_range]
            explore_result.append([self.x, self.y])
            return clear_result, explore_result


if __name__ == '__main__':
    bomb = Property(5, 0, "路径")
    a, b = bomb.trigger(6)
    print(a)
    print(b)
